package net.pulseproject.router.app.model;

import java.util.Collection;

import net.pulseproject.commons.midi.collection.InOutDevices;
import net.pulseproject.commons.midi.entity.MidiSocket;
import net.pulseproject.commons.misc.binder.Bindable;
import net.pulseproject.commons.misc.binder.BindableDelegate;
import net.pulseproject.commons.misc.binder.Binder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Model implements Bindable<Model, ModelField> {

	private static final Log LOG = LogFactory.getLog(Model.class);

	private final BindableDelegate<Model, ModelField> bindableDelegate = new BindableDelegate<Model, ModelField>(this);
	
	private String configurationText;
	
	private Boolean routingActive = Boolean.FALSE;
	
//	private String portFilter;

	/** Actually not a bindable real model value :-/ */
	private String versionString;

	/** Can be null. */
	private Collection<MidiSocket> activeOutgoingSockets;

	private MidiSocket currentSoloedSocket;
	
	private InOutDevices availableDevices;

	
	public final String getConfigurationText() {
		LOG.debug("getConfigurationText(configurationText)");
		return this.configurationText;
	}

	public final void setConfigurationText(final String configurationText) {
		LOG.debug("setConfigurationText(configurationText)");
		if(configurationText == null) { throw new IllegalArgumentException("configurationText == null"); }
		if(configurationText.equals(this.configurationText) == true) { return; }
		
		this.configurationText = configurationText;
		this.bindableDelegate.dispatchBindingEvent(ModelField.CONFIGURATION_TEXT);
	}

	
//	public final String getPortFilter() {
//		LOG.debug("getPortFilter(portFilter)");
//		return this.portFilter;
//	}
//
//	public final void setPortFilter(final String portFilter) {
//		LOG.debug("setPortFilter(portFilter=" + portFilter + ")");
//		if(portFilter == null) { throw new IllegalArgumentException("portFilter == null"); }
//		if(portFilter.equals(this.portFilter) == true) { return; }
//		
//		this.portFilter = portFilter;
//		this.bindableDelegate.dispatchBindingEvent(ModelField.PORT_FILTER);
//	}
	
	public final Boolean isRoutingActive() {
		return this.routingActive;
	}
	
	public final void setRoutingActive(final Boolean routingActive) {
		if(routingActive == null) { throw new IllegalArgumentException("routingActive == null"); }
		if(routingActive.equals(this.routingActive) == true) { return; }
		
		this.routingActive = routingActive;
		this.bindableDelegate.dispatchBindingEvent(ModelField.ROUTING_ACTIVE);
	}

	public final String getVersionString() {
		return this.versionString;
	}
	public final void setVersionString(final String versionString) {
		this.versionString = versionString;
	}

	public final Collection<MidiSocket> getActiveOutgoingSockets() {
		return this.activeOutgoingSockets;
	}

	public final void setActiveOutgoingSockets(final Collection<MidiSocket> activeOutgoingSockets) {
		if(activeOutgoingSockets == null && this.activeOutgoingSockets == null) { return; }
		if(activeOutgoingSockets != null && this.activeOutgoingSockets != null && 
				activeOutgoingSockets.equals(this.activeOutgoingSockets) == true) { return; }
		
		this.activeOutgoingSockets = activeOutgoingSockets;
		this.bindableDelegate.dispatchBindingEvent(ModelField.ACTIVE_OUTGOING_SOCKETS);
	}

	public final MidiSocket getCurrentSoloedSocket() {
		return this.currentSoloedSocket;
	}

	public final void setCurrentSoloedSocket(final MidiSocket currentSoloedSocket) {
		if(currentSoloedSocket == null && this.currentSoloedSocket == null) { return; }
		if(currentSoloedSocket != null && this.currentSoloedSocket != null && 
				currentSoloedSocket.equals(this.currentSoloedSocket) == true) { return; }
		
		this.currentSoloedSocket = currentSoloedSocket;
		this.bindableDelegate.dispatchBindingEvent(ModelField.CURRENT_SOLOED_SOCKET);
	}

	public final InOutDevices getAvailableDevices() {
		return this.availableDevices;
	}

	public final void setAvailableDevices(final InOutDevices availableDevices) {
		if(availableDevices == null && this.availableDevices == null) { return; }
		if(availableDevices != null && this.availableDevices != null && 
				availableDevices.equals(this.availableDevices) == true) { return; }
		
		this.availableDevices = availableDevices;
		this.bindableDelegate.dispatchBindingEvent(ModelField.AVAILABLE_DEVICES);
	}
	
	
	@Override
	public final void addBinding(final Binder<ModelField, ? extends Object> binder) {
		this.bindableDelegate.addBinding(binder);
	}

	@Override
	public final void removeBinding(final Binder<ModelField, ? extends Object> binder) {
		this.bindableDelegate.removeBinding(binder);
	}
	
}
